home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1998 June / SGI Freeware 1998 June.iso / dist / fw_UMINNgopher.idb / usr / freeware / src / gopher_1.12 / object / GSgopherobj.c.z / GSgopherobj.c
Text File  |  1997-09-09  |  10KB  |  514 lines

  1. /********************************************************************
  2.  * $Author: drich $
  3.  * $Revision: 1.1 $
  4.  * $Date: 1995/10/03 04:09:44 $
  5.  * $Source: /proj/freeware1.0/gopher1.12/src/object/RCS/GSgopherobj.c,v $
  6.  * $Status: $
  7.  *
  8.  * Paul Lindner, University of Minnesota CIS.
  9.  *
  10.  * Copyright 1991, 1992 by the Regents of the University of Minnesota
  11.  * see the file "Copyright" in the distribution for conditions of use.
  12.  *********************************************************************
  13.  * MODULE: GSgopherobj.c
  14.  * Implement gopher directory functions.
  15.  *********************************************************************
  16.  * Revision History:
  17.  * $Log: GSgopherobj.c,v $
  18.  * Revision 1.1  1995/10/03  04:09:44  drich
  19.  * gopher 1.2 check-in
  20.  *
  21.  * Revision 1.1.1.3  1993/01/11  19:54:06  lindner
  22.  * Fixed syntax in UCX #defines. (DuH!)
  23.  *
  24.  * Revision 1.1.1.2  1993/01/08  19:00:00  lindner
  25.  * Mods for UCX
  26.  *
  27.  * Revision 1.1.1.1  1992/12/31  05:01:31  lindner
  28.  * Chnages for VMS.
  29.  *
  30.  * Revision 1.1  1992/12/17  21:03:54  jqj
  31.  * Initial revision
  32.  *
  33.  * Revision 1.1  1992/12/10  23:27:52  lindner
  34.  * gopher 1.1 release
  35.  *
  36.  *
  37.  *********************************************************************/
  38.  
  39. #include "GSgopherobj.h"
  40.  
  41. #if defined(mips) && defined(ultrix)   /*** Gross hack, yuck! ***/
  42. #define _SIZE_T
  43. #endif
  44.  
  45. #include "String.h"
  46. #include <stdio.h>
  47. #include "compatible.h"
  48. extern int DEBUG;
  49.  
  50. /*
  51.  * These are needed for GSconnect().  Ick.
  52.  */
  53. #ifdef VMS
  54. #include <socket.h>
  55. #include <in.h>
  56. #include <file.h>
  57. #include <inet.h>
  58. #include <netdb.h>
  59.  
  60. #else
  61. #include <sys/types.h>
  62. #include <sys/socket.h>
  63. #include <netinet/in.h>
  64. #include <sys/file.h>
  65. #ifndef hpux
  66. #include <arpa/inet.h>
  67. #endif
  68. #include <netdb.h>
  69. #endif  /* not VMS */
  70.  
  71. #include "Malloc.h"
  72.  
  73. /*
  74.  * Make a new gopherobj, set the fields accordingly...
  75.  */
  76.  
  77. GopherObj *
  78. GSnewSet(objtype, Title, Selstr, Host, Port)
  79.   char objtype;
  80.   char *Title;
  81.   char *Selstr;
  82.   char *Host;
  83.   int Port;
  84. {
  85.      GopherObj *temp;
  86.  
  87.      temp = (GopherObj *) malloc(sizeof(GopherObj));
  88.      temp->Selstr   = STRnewSet(Selstr);
  89.      temp->Title    = STRnewSet(Title);
  90.      temp->Host     = STRnewSet(Host);
  91.      temp->iPort    = Port;
  92.      GSsetNum(temp, -1);
  93.      GSsetWeight(temp, 0);
  94.  
  95.      return(temp);
  96. }
  97.  
  98.  
  99. /*
  100.  * Make a new gopherobj...  Should reuse destroyed GopherObjs...
  101.  */
  102.  
  103. GopherObj *
  104. GSnew()
  105. {
  106.      GopherObj *temp;
  107.  
  108.      temp = (GopherObj *) malloc(sizeof(GopherObj));
  109.      temp->Selstr = STRnew();
  110.      temp->Title  = STRnew();
  111.      temp->Host   = STRnew();
  112.  
  113.      GSinit(temp);
  114.      
  115.      return(temp);
  116. }
  117.  
  118. void
  119. GSdestroy(gs)
  120.   GopherObj *gs;
  121. {
  122.      STRdestroy(gs->Selstr);
  123.      STRdestroy(gs->Title);
  124.      STRdestroy(gs->Host);
  125.  
  126.      free(gs);
  127. }
  128.      
  129.  
  130.  
  131. /*
  132.  * Clear out all the crud 
  133.  */
  134.  
  135. void
  136. GSinit(gs)
  137.   GopherObj *gs;
  138. {
  139.      GSsetType(gs, '\0');
  140.      
  141.      STRinit(gs->Title);
  142.      STRinit(gs->Selstr);
  143.      STRinit(gs->Host);
  144.  
  145.      gs->iPort = 0;
  146.      GSsetNum(gs, -1);
  147.      GSsetWeight(gs, 0);
  148. }
  149.  
  150.  
  151. void
  152. GStoNet(gs, sockfd)
  153.   GopherObj *gs;
  154.   int sockfd;
  155. {
  156.      static char buf[1024];
  157.  
  158.      buf[0] = GSgetType(gs);
  159.  
  160.      sprintf(buf + 1, "%s\t%s\t%s\t%d\r\n",
  161.          GSgetTitle(gs),
  162.          GSgetPath(gs),
  163.          GSgetHost(gs),
  164.          GSgetPort(gs));
  165.      
  166.      writestring(sockfd, buf);
  167.      
  168.      if (DEBUG)
  169.       fprintf(stderr, buf);
  170.  
  171. }
  172.  
  173.  
  174. void
  175. GStoNetHTML(gs, sockfd)
  176.   GopherObj *gs;
  177.   int sockfd;
  178. {
  179.      static char buf[1024];
  180.      static char pathbuf[1024];
  181.  
  182.      buf[0] = '\0';
  183.      pathbuf[0] = '\0';
  184.  
  185.      /** Convert Path so that spaces are %20 **/
  186.      Tohexstr(GSgetPath(gs), pathbuf);
  187.  
  188.      sprintf(buf, "<A HREF=http://%s:%d/%s>%s</A>",
  189.          GSgetHost(gs),
  190.          GSgetPort(gs),
  191.          pathbuf,
  192.          GSgetTitle(gs));
  193.  
  194.      writestring(sockfd, buf);
  195.  
  196.      if (DEBUG)
  197.       fprintf(stderr, "HTML: %s", buf);
  198.      
  199.      if (GSgetWeight(gs) != 0) {
  200.       sprintf(buf, "Score: %d\r\n", GSgetWeight(gs));
  201.       writestring(sockfd, buf);
  202.      }
  203.      else
  204.       writestring(sockfd, "\r\n");
  205.  
  206. }
  207.  
  208.  
  209. /*
  210.  * Fill in a GopherObj, given an HREF= link from a WWW anchor..
  211.  * So far only works with http
  212.  */
  213.  
  214. void
  215. GSfromHREF(gs, href)
  216.   GopherObj *gs;
  217.   char *href;
  218. {
  219.      char *cp;
  220.      char *host;
  221.      char path[1024];
  222.      
  223.      if (strncasecmp(href, "http://", 7)==0) {
  224.       host = href +7;
  225.       cp  = strchr(href+7, '/');
  226.       if (cp == NULL)
  227.            return;
  228.       
  229.       *cp = '\0';
  230.       strcpy(path, "GET ");
  231.       strcat(path, cp+1);
  232.       GSsetPath(gs, path);
  233.  
  234.       GSsetType(gs, 'h');
  235.  
  236.       GSsetPath(gs, path);
  237.       
  238.       cp = strchr(host, ':');
  239.       if (cp==NULL) 
  240.            GSsetPort(gs, 80);  /** default WWW port **/
  241.       else {
  242.            GSsetPort(gs, atoi(cp+1));
  243.            *cp = '\0';
  244.       }
  245.  
  246.       GSsetHost(gs, host);
  247.      }
  248. }
  249.       
  250.  
  251.  
  252.  
  253. extern int readfield();
  254. extern int readline();
  255.  
  256. int
  257. GSfromNet(gs, sockfd)
  258.   GopherObj *gs;
  259.   int sockfd;
  260. {
  261.      char foo[1024];
  262.      
  263.      if (readfield(sockfd, foo, 1024)<= 0) {
  264.       /* EOF or error */
  265.       return(-1);
  266.      }
  267.  
  268.      GSsetType(gs, foo[0]);
  269.  
  270.      /** Get the kind of file from the first character **/
  271.      /** Filter out files that we can't deal with **/
  272.  
  273.      switch (GSgetType(gs)) {
  274.        case A_FILE:
  275.        case A_DIRECTORY:
  276.        case A_MACHEX:
  277.        case A_PCBIN:
  278.        case A_CSO:
  279.        case A_INDEX:
  280.        case A_TELNET:
  281.        case A_SOUND:
  282.        case A_UNIXBIN:
  283.        case A_GIF:
  284.        case A_HTML:
  285.        case A_TN3270:
  286.        case A_MIME:
  287.        case A_IMAGE:
  288.       break;
  289.        case A_EOI:
  290.       if (foo[1] == '\r' && foo[2] == '\n')
  291.            return(1);
  292.      default:
  293.     return(-2);  
  294.      }
  295.  
  296.      /** Suck off the User Displayable name **/
  297.      GSsetTitle(gs, foo+1);
  298.      
  299.      /** Suck off the Pathname **/
  300.      if (readfield(sockfd, foo, 1024) == 0)
  301.       return(-1);
  302.      GSsetPath(gs, foo);
  303.  
  304.      /** Suck off the hostname **/
  305.      if (readfield(sockfd, foo, 1024) == 0)
  306.       return(-1);
  307.      GSsetHost(gs, foo);
  308.  
  309.      if (readline(sockfd, foo, 1024)==0)
  310.       return(-1); 
  311.  
  312.      GSsetPort(gs, 0);
  313.  
  314.      /** Get the port number **/
  315.      GSsetPort(gs, atoi(foo));
  316.  
  317.      return(0);
  318. }
  319.  
  320. /** Copy a GopherObj ***/
  321.  
  322. void
  323. GScpy(dest, orig)
  324.   GopherObj *dest, *orig;
  325. {
  326.      dest->sFileType = orig->sFileType;
  327.      dest->iPort     = orig->iPort;
  328.      dest->Itemnum   = orig->Itemnum;
  329.  
  330.      GSsetTitle(dest, GSgetTitle(orig));
  331.      GSsetPath(dest, GSgetPath(orig));
  332.      GSsetHost(dest, GSgetHost(orig));
  333. }
  334.  
  335. /** Compare two GopherObjs ***/
  336.  
  337. int
  338. GScmp(gs1, gs2)
  339.   GopherObj *gs1, *gs2;
  340. {
  341.      if (GSgetTitle(gs1) == NULL)
  342.       return(1);
  343.      if (GSgetTitle(gs2) == NULL)
  344.       return(-1);
  345.  
  346.      return(strcmp(GSgetTitle(gs1), GSgetTitle(gs2)));
  347. }
  348.  
  349.  
  350.  
  351.  
  352. /* GSconnect performs a connection to socket 'service' on host
  353.  * 'host'.  Host can be a hostname or ip-address.  If 'host' is null, the
  354.  * local host is assumed.   The parameter full_hostname will, on return,
  355.  * contain the expanded hostname (if possible).  Note that full_hostname is a
  356.  * pointer to a char *, and is allocated by connect_to_gopher()
  357.  *
  358.  * Errors:
  359.  *
  360.  * -1 get service failed
  361.  *
  362.  * -2 get host failed
  363.  *
  364.  * -3 socket call failed
  365.  *
  366.  * -4 connect call failed
  367.  */
  368.  
  369. int
  370. GSconnect(gs)
  371.   GopherObj *gs;
  372. {
  373.      struct sockaddr_in Server;
  374.      struct hostent *HostPtr;
  375.      int iSock = 0;
  376.      int ERRinet = -1;
  377.  
  378. #ifdef _CRAY
  379.      ERRinet = 0xFFFFFFFF;  /* -1 doesn't sign extend on 64 bit machines */
  380. #endif
  381.  
  382.      /*** Find the hostname address ***/
  383.      
  384.      if ((Server.sin_addr.s_addr = inet_addr(GSgetHost(gs))) == ERRinet) {
  385.       if (HostPtr = gethostbyname(GSgetHost(gs))) {
  386.            bzero((char *) &Server, sizeof(Server));
  387.            bcopy(HostPtr->h_addr, (char *) &Server.sin_addr, HostPtr->h_length);
  388.            Server.sin_family = HostPtr->h_addrtype;
  389.       } else
  390.            return (-2);
  391.      } else
  392.       Server.sin_family = AF_INET;
  393.  
  394.      Server.sin_port = (unsigned short) htons(GSgetPort(gs));
  395.  
  396.      /*** Open the socket ***/
  397.  
  398.      if ((iSock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  399.       return (-3);
  400.  
  401. #ifndef UCX
  402.      setsockopt(iSock, SOL_SOCKET, ~SO_LINGER, 0, 0);
  403. #endif
  404.  
  405.      setsockopt(iSock, SOL_SOCKET, SO_REUSEADDR, 0, 0);
  406.      setsockopt(iSock, SOL_SOCKET, SO_KEEPALIVE, 0, 0);
  407.  
  408.      /*** Connect ***/
  409.  
  410.      if (connect(iSock, (struct sockaddr *) &Server, sizeof(Server)) < 0) {
  411.       closenet(iSock);
  412.       return (-4);
  413.      }
  414.      return(iSock);
  415. }
  416.  
  417. /*
  418.  * GSfromLink takes an open file descriptor and starts reading from it.
  419.  * It keeps going until it findsL
  420.  *    enough fields for a gopherobj
  421.  *    no data left
  422.  * 
  423.  * returns 0 with success, -1 on an error.
  424.  */
  425.  
  426. #define    G_PATH    (1<<0)
  427. #define    G_TYPE  (1<<1)
  428. #define    G_NAME    (1<<2)
  429. #define    G_PORT    (1<<3)
  430. #define    G_HOST    (1<<4)
  431. #define    G_ALL (G_PATH | G_TYPE | G_NAME | G_PORT | G_HOST)
  432.  
  433. int
  434. GSfromLink(gs, fd, host, port)
  435.   GopherObj *gs;
  436.   int       fd;
  437.   char      *host;
  438.   int       port;
  439. {
  440.      int doneflags = 0;
  441.      char buf[1024];
  442.  
  443.      while ((doneflags != G_ALL) && readline(fd, buf, 1024)) {
  444.       if (buf[0] == '#')
  445.            continue;   /* comment */
  446.  
  447.       ZapCRLF(buf);
  448.  
  449.       if (strncmp(buf, "Type=", 5)==0) {
  450.            GSsetType(gs, buf[5]);
  451.            doneflags |= G_TYPE;
  452.       }
  453.       
  454.       if (strncmp(buf, "Name=", 5)==0) {
  455.            GSsetTitle(gs, buf+5);
  456.            doneflags |= G_NAME;
  457.       }
  458.        
  459.       if (strncmp(buf, "Path=", 5)==0) {
  460.            GSsetPath(gs, buf+5);
  461.            doneflags |= G_PATH;
  462.       }
  463.        
  464.       if (strncmp(buf, "Host=", 5)==0) {
  465.            if (buf[5] == '+' && buf[6] == '\0')
  466.             GSsetHost(gs, host);
  467.            else
  468.             GSsetHost(gs, buf+5);
  469.  
  470.            doneflags |= G_HOST;
  471.       }
  472.       if (strncmp(buf, "Port=", 5)==0) {
  473.            if (buf[5] == '+' && buf[6] == '\0')
  474.             GSsetPort(gs, port);
  475.            else
  476.             GSsetPort(gs, atoi(buf+5));
  477.  
  478.            doneflags |= G_PORT;
  479.       }
  480.       if (strncmp(buf, "Numb=", 5)==0)
  481.            GSsetNum(gs, atoi(buf+5));
  482.       
  483.      }
  484.      return ((doneflags == G_ALL) ? 0 : -1); /* 0 == success */
  485. }
  486.  
  487.  
  488. void
  489. GStoLink(gs, fd)
  490.   GopherObj *gs;
  491.   int fd;
  492. {
  493.      char gtype[2];
  494.      char portnum[16];
  495.      
  496.      gtype[0] = GSgetType(gs);
  497.      gtype[1] = '\0';
  498.  
  499.      writestring(fd, "#");
  500.      writestring(fd, "\nType=");
  501.      writestring(fd, gtype);
  502.      writestring(fd, "\nName=");
  503.      writestring(fd, GSgetTitle(gs));
  504.      writestring(fd, "\nPath=");
  505.      writestring(fd, GSgetPath(gs));
  506.      writestring(fd, "\nHost=");
  507.      writestring(fd, GSgetHost(gs));
  508.      writestring(fd, "\nPort=");
  509.      sprintf(portnum, "%d", GSgetPort(gs));
  510.      writestring(fd, portnum);
  511.      writestring(fd, "\n");
  512. }
  513.  
  514.